package com.lagou.zkconfig;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@SpringBootApplication
public class ZkconfigApplication {

    private static HikariDataSource hikariDataSource;

    private static ZkClient zkClient;

    private static ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) {
        SpringApplication.run(ZkconfigApplication.class, args);

        //初始化zookeeper
        initZookeeper();

        //配置数据库连接池
        configHikariSource();


    }


    /**
     * 初始化Zookeeper连接
     */
    private static void initZookeeper() {

        zkClient = new ZkClient("192.168.139.121:2181");

        zkClient.setZkSerializer(new ZkStrSerializer());

        zkClient.subscribeDataChanges("/jdbc", new IZkDataListener() {

            public void handleDataChange(String path, Object data) {

                System.out.println(path + " data is changed, new data " + data);

                hikariDataSource.close();

                //节点变化 配置数据源
                configHikariSource();
            }

            public void handleDataDeleted(String path) {

                System.out.println(path + " is deleted!!");

                hikariDataSource.close();
            }
        });
    }

    /**
     * 配置数据库连接池
     */
    private static void configHikariSource() {

        // 1. 从 zookeeper 中获取配置信息
        JDBCConfig myConfig = getJDBCConfig();
        // 2. 更新 hikari 配置
        updateHikariConfig(myConfig);
        try {
            //  3. 执行测试 sql
            executeTestSQL();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


    private static JDBCConfig getJDBCConfig() {

        Object data = zkClient.readData("/jdbc");

        try {
            JDBCConfig myConfig = mapper.readValue(data.toString(), JDBCConfig.class);

            System.out.println(myConfig.toString());

            return myConfig;

        } catch (JsonProcessingException e) {

            return new JDBCConfig();
        }
    }

    private static void updateHikariConfig(JDBCConfig myConfig) {

        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(myConfig.getUrl());
        config.setUsername(myConfig.getUsername());
        config.setPassword(myConfig.getPassword());
        config.addDataSourceProperty("driverClassName", myConfig.getDriver());
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        hikariDataSource = new HikariDataSource(config);
    }

    private static void executeTestSQL() throws SQLException {

        Connection connection = hikariDataSource.getConnection();

        PreparedStatement pst = connection.prepareStatement("select host from user");

        ResultSet rs = pst.executeQuery();

        while (rs.next()) {

            System.out.println("host : " + rs.getString(1));
        }
    }


}
